from PySide2.QtGui import QStandardItemModel, QStandardItem, QIcon
from PySide2.QtWidgets import QMainWindow, QVBoxLayout, QHBoxLayout, QWidget, QComboBox, QLineEdit, QTableView, \
    QSizePolicy, QHeaderView, QMenu, QApplication, QTabWidget, QPushButton, QMessageBox
from PySide2.QtCore import Qt, Signal
from PySide2.QtGui import QIcon
import pandas as pd
from pypinyin import lazy_pinyin

import bastion_loader
import bastion_page_loader
import captcha_recognizer
import time
import os,sys
from auto_login import AutoLogin
from config_dialog import ConfigDialog
from servers_config_dialog import ServersConfigDialog
import config_manager
# 修改这行
from logger_config import ui_logger as main_window_logger
import threading
import logging
import servers_config_manager


def resource_path(relative_path):
    """获取打包后资源的绝对路径"""
    try:
        # PyInstaller 创建的临时文件夹路径
        base_path = sys._MEIPASS
    except Exception:
        # 正常开发环境下的路径
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)



class MainWindow(QMainWindow):
    show_error_signal = Signal(str, str)  # 标题, 消息
    show_info_signal = Signal(str, str)   # 标题, 消息
    show_status_signal = Signal(str)      # 状态栏文本
    remove_status_signal = Signal()       # 移除状态栏文本

    def __init__(self):
        super().__init__()
        self.setWindowTitle("堡垒机助手")
        self.resize(1200, 800)
        main_window_logger.info("主窗口初始化开始")

        # 先初始化 config
        self.config = config_manager.ConfigManager()
        # 再初始化 servers_config
        self.servers_config = servers_config_manager.ConfigManager()
        # 再初始化 auto_submit
        self.auto_submit = self.config.get_auto_submit()

        # 设置窗口图标
        icon_path = resource_path('blj.ico')
        if os.path.exists(icon_path):
            self.setWindowIcon(QIcon(icon_path))

        # 从配置加载窗口大小
        width, height = self.config.get_window_size()
        self.resize(width, height)

        # 创建主控件和布局
        central_widget = QWidget()
        layout = QVBoxLayout()

        # 创建标签页控件
        self.tabWidget = QTabWidget()

        # 创建"堡垒机"标签页
        self.bastion_tab = QWidget()
        bastion_layout = QVBoxLayout(self.bastion_tab)

        # 搜索布局
        search_layout = QHBoxLayout()

        # 添加配置按钮
        self.config_button = QPushButton("配置")
        self.config_button.setToolTip("程序相关配置")
        self.config_button.clicked.connect(self.show_config_dialog)


        # 添加重新加载按钮
        self.reload_button = QPushButton("重新加载")
        self.reload_button.setToolTip("重新加载堡垒机信息")
        self.reload_button.clicked.connect(self.reload_all_config)

        self.search_field = QComboBox()
        self.search_field.addItems(["路段名称", "堡垒机IP", "用户名", "堡垒机品牌", "备注"])
        self.search_box = QLineEdit()
        self.search_box.setPlaceholderText("输入搜索内容...")
        self.search_box.textChanged.connect( lambda text: self.check_filter_items(self.search_field, self.table_view, text))


        # 在"路段服务器"标签页的搜索布局中添加编辑按钮
        self.edit_save_button = QPushButton("编辑表格")
        self.edit_save_button.setToolTip("编辑/保存表格数据")
        self.is_editing = False
        self.edit_save_button.setText("编辑表格")

        # 将按钮添加到搜索布局
        # search_layout2.addWidget(self.edit_save_button2)

        # 添加提交/不提交按钮
        self.submit_button = QPushButton()
        self.submit_button.setToolTip("控制自动登录是否自动提交登录")
        self.auto_submit = self.config.get_auto_submit()
        if self.auto_submit:
            self.submit_button.setText("不提交")
        else:
            self.submit_button.setText("提交登录")
        self.submit_button.clicked.connect(self.toggle_auto_submit)

        # 添加置顶按钮
        self.top_button = QPushButton("窗口置顶")
        self.top_button.clicked.connect(self.toggle_window_top)

        # 从配置加载置顶状态
        config = config_manager.ConfigManager()
        if config.get_window_on_top():
            self.toggle_window_top()


        search_layout.addWidget(self.search_field)
        search_layout.addWidget(self.search_box)
        search_layout.addWidget(self.config_button)
        search_layout.addWidget(self.reload_button)
        search_layout.addWidget(self.edit_save_button)
        search_layout.addWidget(self.submit_button)
        search_layout.addWidget(self.top_button)


        # 表格视图
        self.table_view = QTableView()
        self.table_view.setSortingEnabled(True)
        self.table_view.setSelectionBehavior(QTableView.SelectItems)  # 允许选择单个单元格
        self.table_view.setEditTriggers(QTableView.NoEditTriggers)  # 禁止编辑
        self.table_view.setSelectionMode(QTableView.ContiguousSelection)  # 允许连续选择
        self.table_view.setContextMenuPolicy(Qt.CustomContextMenu)
        self.table_view.customContextMenuRequested.connect( lambda text : self.show_context_menu(self.table_view, text))
        self.table_view.clicked.connect(lambda index: self.copy_cell_on_click(self.table_view, index))
        self.set_table_style(self.table_view)
        self.table_view.doubleClicked.connect(self.on_table_double_clicked)

        # 将控件添加到堡垒机标签页布局
        bastion_layout.addLayout(search_layout)
        bastion_layout.addWidget(self.table_view, stretch=1)

        # 创建"路段服务器"标签页
        self.server_tab = QWidget()
        server_layout = QVBoxLayout(self.server_tab)
        # 这里可以添加路段服务器相关的控件
        # server_layout.add(...)

        # 搜索布局
        search_layout2 = QHBoxLayout()
        self.search_field2 = QComboBox()
        self.search_field2.addItems(["路段", "分类", "跳机"])
        self.search_box2 = QLineEdit()
        self.search_box2.setPlaceholderText("输入搜索内容...")
        self.search_box2.textChanged.connect(lambda text: self.check_filter_items(self.search_field2, self.table_view2, text))

        # 添加配置按钮
        self.servers_reload_button = QPushButton("重新加载")
        self.servers_reload_button.setToolTip("重新加载配置信息")
        self.servers_reload_button.clicked.connect(self.reload_all_config)

        # 添加配置按钮
        self.servers_config_button = QPushButton("配置")
        self.servers_config_button.setToolTip("配置路段服务器文件路径")
        self.servers_config_button.clicked.connect(self.servers_show_config_dialog)

        # 添加编辑按钮
        self.edit_save_button2 = QPushButton("编辑表格")
        self.edit_save_button2.setToolTip("编辑/保存表格数据")
        self.is_editing2 = False
        self.edit_save_button2.setText("编辑表格")

        search_layout2.addWidget(self.search_field2)
        search_layout2.addWidget(self.search_box2)
        search_layout2.addWidget(self.servers_reload_button)
        search_layout2.addWidget(self.servers_config_button)
        # 将按钮添加到搜索布局
        search_layout2.addWidget(self.edit_save_button2)

        # 表格视图
        self.table_view2 = QTableView()
        self.table_view2.setSortingEnabled(True)
        self.table_view2.setSelectionBehavior(QTableView.SelectItems)
        self.table_view2.setEditTriggers(QTableView.NoEditTriggers)
        self.table_view2.setContextMenuPolicy(Qt.CustomContextMenu)
        self.table_view2.customContextMenuRequested.connect(lambda pos: self.show_context_menu(self.table_view2, pos))
        self.table_view2.clicked.connect(lambda index: self.copy_cell_on_click(self.table_view2, index))
        self.set_table_style(self.table_view2)

        # 将控件添加到路段服务器标签页布局
        server_layout.addLayout(search_layout2)
        server_layout.addWidget(self.table_view2, stretch=1)


        # 添加标签页
        self.tabWidget.addTab(self.bastion_tab, "堡垒机")
        self.tabWidget.addTab(self.server_tab, "路段服务器")

        # 将标签页控件添加到主布局
        layout.addWidget(self.tabWidget)
        central_widget.setLayout(layout)
        self.setCentralWidget(central_widget)

        # 初始化配置管理器后，立即加载数据
        self.load_bastion_data()
        self.load_servers_data()
        self.bastion_loader = bastion_page_loader.BastionPageLoader()
        main_window_logger.info("主窗口初始化完成")

        # 信号连接
        self.show_error_signal.connect(self._show_error_box)
        self.show_info_signal.connect(self._show_info_box)
        self.show_status_signal.connect(self._show_status_label)
        self.remove_status_signal.connect(self._remove_status_label)
        self._status_label = None
        # 连接按钮信号
        self.edit_save_button2.clicked.connect(self.toggle_edit_mode2)

        # 将按钮的信号连接移动到__init__方法的末尾，确保方法已定义
        self.edit_save_button.clicked.connect(self.toggle_edit_mode)
        # self.top_button.clicked.connect(self.toggle_window_top)

    def toggle_window_top(self):
        """切换窗口置顶状态"""
        # 判断当前是否置顶
        is_top = self.windowFlags() & Qt.WindowStaysOnTopHint
        if not is_top:
            self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
            self.top_button.setText("取消置顶")
            # config = config_manager.ConfigManager()
            # config.set_window_on_top(True)
            main_window_logger.info("窗口置顶状态切换: True")
        else:
            self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint)
            self.top_button.setText("窗口置顶")
            # config = config_manager.ConfigManager()
            # config.set_window_on_top(False)
            main_window_logger.info("窗口置顶状态切换: False")
        self.show()

    def toggle_auto_submit(self):
        """切换自动提交状态"""
        if self.auto_submit:
            self.submit_button.setText("提交登录")
            main_window_logger.info("自动提交已禁用")
        else:
            self.submit_button.setText("不提交")
            main_window_logger.info("自动提交已启用")
        self.auto_submit = not self.auto_submit
        # self.config.set_auto_submit(self.auto_submit)
        # main_window_logger.info(f"自动提交状态已保存: {self.auto_submit}")

    def toggle_edit_mode(self):
        """切换编辑模式"""
        print(f"toggle_edit_mode called. self.is_editing: {self.is_editing}") # Debug print
        if self.is_editing:
            # 当前是编辑模式，切换到保存模式
            print("当前是编辑模式，切换到保存模式")
            try:
                self.save_table_data()
                self.table_view.setEditTriggers(QTableView.NoEditTriggers)
                self.edit_save_button.setText("编辑表格")
                self.is_editing = False
                # main_window_logger.info("退出编辑模式并保存数据")
                # self.show_info_signal.emit("成功", "数据已保存")
            except Exception as e:
                main_window_logger.error(f"保存数据失败: {e}")
                self.show_error_signal.emit("错误", f"保存数据失败: {e}")
        else:
            # 当前是查看模式，切换到编辑模式
            print("当前是查看模式，切换到编辑模式")
            self.table_view.setEditTriggers(QTableView.DoubleClicked | QTableView.EditKeyPressed)
            self.edit_save_button.setText("保存")
            self.is_editing = True
            main_window_logger.info("进入编辑模式")
            self.show_info_signal.emit("提示", "已进入编辑模式，双击单元格可编辑")

    def toggle_edit_mode2(self):
        """切换路段服务器表格的编辑模式"""
        print(f"toggle_edit_mode2 called. self.is_editing2: {self.is_editing2}")
        if self.is_editing2:
            # 当前是编辑模式，切换到保存模式
            print("当前是编辑模式，切换到保存模式")
            try:
                self.save_table_data2()
                self.table_view2.setEditTriggers(QTableView.NoEditTriggers)
                self.edit_save_button2.setText("编辑表格")
                self.is_editing2 = False
            except Exception as e:
                main_window_logger.error(f"保存数据失败: {e}")
                self.show_error_signal.emit("错误", f"保存数据失败: {e}")
        else:
            # 当前是查看模式，切换到编辑模式
            print("当前是查看模式，切换到编辑模式")
            self.table_view2.setEditTriggers(QTableView.DoubleClicked | QTableView.EditKeyPressed)
            self.edit_save_button2.setText("保存")
            self.is_editing2 = True
            main_window_logger.info("进入路段服务器编辑模式")
            self.show_info_signal.emit("提示", "已进入编辑模式，双击单元格可编辑")

    def save_table_data(self):
        """保存表格数据到Excel文件"""
        model = self.table_view.model()
        if model is None:
            raise Exception("表格模型为空")
        
        # 获取表头
        headers = []
        for col in range(model.columnCount()):
            headers.append(model.headerData(col, Qt.Horizontal))
        
        # 获取数据
        data = []
        for row in range(model.rowCount()):
            row_data = []
            for col in range(model.columnCount()):
                index = model.index(row, col)
                row_data.append(model.data(index))
            data.append(row_data)
        
        # 创建DataFrame并保存
        df = pd.DataFrame(data, columns=headers)
        
        # 获取原始文件路径
        config = config_manager.ConfigManager()
        file_path = config.get_bastion_file_path()
        if not file_path:
            raise Exception("未配置堡垒机文件路径")
        
        df.to_excel(file_path, sheet_name='路段服务器', index=False)
        main_window_logger.info(f"数据已保存到: {file_path}")

    def save_table_data2(self):
        """保存路段服务器表格数据到Excel文件"""
        model = self.table_view2.model()
        if model is None:
            raise Exception("表格模型为空")

        # 获取表头
        headers = []
        for col in range(model.columnCount()):
            headers.append(model.headerData(col, Qt.Horizontal))

        # 获取数据
        data = []
        for row in range(model.rowCount()):
            row_data = []
            for col in range(model.columnCount()):
                index = model.index(row, col)
                row_data.append(model.data(index))
            data.append(row_data)

        # 创建DataFrame并保存
        df = pd.DataFrame(data, columns=headers)

        # 获取原始文件路径
        config = servers_config_manager.ConfigManager()
        file_path = config.get_servers_path()
        if not file_path:
            raise Exception("未配置路段服务器文件路径")

        df.to_excel(file_path, sheet_name='路段服务器', index=False)
        main_window_logger.info(f"路段服务器数据已保存到: {file_path}")

    def toggle_edit_mode2(self):
        """切换路段服务器表格的编辑模式"""
        print(f"toggle_edit_mode2 called. self.is_editing2: {self.is_editing2}")
        if self.is_editing2:
            # 当前是编辑模式，切换到保存模式
            print("当前是编辑模式，切换到保存模式")
            try:
                self.save_table_data2()
                self.table_view2.setEditTriggers(QTableView.NoEditTriggers)
                self.edit_save_button2.setText("编辑表格")
                self.is_editing2 = False
            except Exception as e:
                main_window_logger.error(f"保存数据失败: {e}")
                self.show_error_signal.emit("错误", f"保存数据失败: {e}")
        else:
            # 当前是查看模式，切换到编辑模式
            print("当前是查看模式，切换到编辑模式")
            self.table_view2.setEditTriggers(QTableView.DoubleClicked | QTableView.EditKeyPressed)
            self.edit_save_button2.setText("保存")
            self.is_editing2 = True
            main_window_logger.info("进入路段服务器编辑模式")
            self.show_info_signal.emit("提示", "已进入编辑模式，双击单元格可编辑")

    def save_table_data2(self):
        """保存路段服务器表格数据到Excel文件"""
        model = self.table_view2.model()
        if model is None:
            raise Exception("表格模型为空")

        # 获取表头
        headers = []
        for col in range(model.columnCount()):
            headers.append(model.headerData(col, Qt.Horizontal))

        # 获取数据
        data = []
        for row in range(model.rowCount()):
            row_data = []
            for col in range(model.columnCount()):
                index = model.index(row, col)
                row_data.append(model.data(index))
            data.append(row_data)

        # 创建DataFrame并保存
        df = pd.DataFrame(data, columns=headers)

        # 获取原始文件路径
        config = servers_config_manager.ConfigManager()
        file_path = config.get_servers_path()
        if not file_path:
            raise Exception("未配置路段服务器文件路径")

        df.to_excel(file_path, sheet_name='路段服务器', index=False)
        main_window_logger.info(f"路段服务器数据已保存到: {file_path}")

    def load_bastion_data(self):
        # 重置窗口大小
        config = config_manager.ConfigManager()
        width, height = config.get_window_size()
        self.resize(width, height)

        """从Excel文件加载堡垒机数据"""
        data_loader = bastion_loader.BastionLoader()
        data_loader.load_data()
        data = data_loader.get_sorted_data()
        # 创建模型并设置表头
        model = ChineseSortModel()
        # 使用配置的堡垒机表格列名
        configured_bastion_columns = self.config.get_bastion_columns()
        model.setHorizontalHeaderLabels(configured_bastion_columns)

        # 填充数据
        for row in data.itertuples():
            items = [QStandardItem(str(col)) for col in row[1:]]
            for item in items:
                item.setFlags(item.flags() | Qt.ItemIsEditable) # 确保单元格可编辑
            model.appendRow(items)

        # 设置模型到表格视图
        self.table_view.setModel(model)

        # 在加载数据后，根据当前编辑模式重新设置编辑触发器
        if self.is_editing:
            self.table_view.setEditTriggers(QTableView.DoubleClicked | QTableView.EditKeyPressed)
        else:
            self.table_view.setEditTriggers(QTableView.NoEditTriggers)

        # 设置列宽
        header = self.table_view.horizontalHeader()
        # 注意：这里设置的是固定列宽，可能需要根据实际列数调整
        for i, column_width in enumerate([100, 120, 120, 120,100]):  # 根据需要调整宽度
            if i < len(configured_bastion_columns) - 1: # 最后一列自动拉伸
                header.setSectionResizeMode(i, QHeaderView.Fixed)
                self.table_view.setColumnWidth(i, column_width)
            else:
                header.setSectionResizeMode(i, QHeaderView.Stretch)

    def show_context_menu(self,table_view , pos):
        """显示右键菜单"""
        menu = QMenu(table_view)
        copy_action = menu.addAction("复制")
        copy_action.triggered.connect(lambda: self.copy_selected_text(table_view))
        menu.exec_(table_view.viewport().mapToGlobal(pos))

    def copy_selected_text(self,table_view):
        """复制选中的文本"""
        selection = table_view.selectionModel()
        if not selection.hasSelection():
            return

        selected_indexes = selection.selectedIndexes()
        if not selected_indexes:
            return

        # 按行分组选中的单元格
        rows = {}
        for index in selected_indexes:
            row = index.row()
            if row not in rows:
                rows[row] = []
            rows[row].append(index)

        # 按行和列顺序组织文本
        text_lines = []
        for row in sorted(rows.keys()):
            # 按列顺序排列单元格内容
            cells = sorted(rows[row], key=lambda idx: idx.column())
            text_lines.append("\t".join(idx.data() for idx in cells))

        # 合并所有行，用换行符分隔
        text = "\n".join(text_lines)
        clipboard = QApplication.clipboard()
        clipboard.setText(text)

    def copy_cell_on_click(self,table_view, index):
        """单击单元格时复制文本"""
        # 如果是编辑模式，禁用单击复制
        if table_view == self.table_view and self.is_editing:
            return
        if table_view == self.table_view2 and self.is_editing2:
            return

        if index.isValid():
            text = index.data()
            clipboard = QApplication.clipboard()
            clipboard.setText(str(text))


    def check_filter_items(self,search_field,table_view, text):
        # 搜索框内容变化时，根据搜索框内容过滤表格中的行
        model = table_view.model()
        if model is None:
            return
        # 获取选中的字段
        selected_field = search_field.currentText()
        # print(selected_field)

        # 获取表头标签
        header_labels = [table_view.model().headerData(i, Qt.Horizontal) for i in range(model.columnCount())]
        # print(header_labels)

        # 找到选中的字段在表格中的索引
        try:
            column_index = header_labels.index(selected_field)
        except ValueError:
            # 如果选中的字段不在表头中，直接返回
            return

        for row in range(model.rowCount()):
            index = model.index(row, column_index)
            item_text = model.data(index)
            if item_text is not None and text.lower() in item_text.lower():
                table_view.setRowHidden(row, False)
            else:
                table_view.setRowHidden(row, True)

    def on_table_double_clicked(self, index):
        """处理表格双击事件"""
        print(f"on_table_double_clicked called. self.is_editing: {self.is_editing}") # Debug print
        if self.is_editing:
            return
        else:
            main_window_logger.info("双击表格行，准备打开堡垒机页面")
            model = self.table_view.model()
            if model is None:
                main_window_logger.warning("表格模型为空")
                return
            header_labels = [self.table_view.model().headerData(i, Qt.Horizontal) for i in range(model.columnCount())]
            try:
                ip_column_index = header_labels.index("堡垒机IP")
                name_column_index = header_labels.index("路段名称")
                user_column_index = header_labels.index("用户名")
                pwd_column_index = header_labels.index("登录密码")
                brand_column_index = header_labels.index("堡垒机品牌")
            except ValueError:
                return
            ip_index = model.index(index.row(), ip_column_index)
            bastion_ip = model.data(ip_index)
            name_index = model.index(index.row(), name_column_index)
            bastion_name = model.data(name_index)
            user_index = model.index(index.row(), user_column_index)
            username = model.data(user_index)
            pwd_index = model.index(index.row(), pwd_column_index)
            password = model.data(pwd_index)
            brand_index = model.index(index.row(), brand_column_index)
            brand = model.data(brand_index)
            if bastion_ip:
                # 线程安全：用信号让主线程添加状态栏
                self.show_status_signal.emit(f"正在打开堡垒机页面: {bastion_name}...")
                def open_bastion_in_thread():
                    url = f"https://{bastion_ip}"
                    main_window_logger.info(f"准备打开堡垒机页面: {url}")
                    # 确保驱动已初始化
                    if not self.bastion_loader.initialize_driver():
                        main_window_logger.error("初始化浏览器驱动失败")
                        self.show_error_signal.emit("错误", "初始化浏览器驱动失败")
                        self.remove_status_signal.emit()
                        return
                    # 打开堡垒机页面
                    if not self.bastion_loader.open_bastion_page(url, bastion_name):
                        main_window_logger.error("打开堡垒机页面失败")
                        self.show_error_signal.emit("错误", "打开堡垒机页面失败")
                        self.remove_status_signal.emit()
                        return
                    # 自动登录
                    main_window_logger.info(f"开始自动登录堡垒机: {bastion_name}, IP: {bastion_ip}, 用户名: {username}")
                    auto_login = AutoLogin(self.bastion_loader.driver, title=bastion_name, auto_submit=self.auto_submit)
                    try:
                        main_window_logger.info(f"开始执行自动登录操作")
                        time.sleep(1) # 新增：等待1秒钟再执行自动登录
                        auto_login.login(username, password)
                        main_window_logger.info(f"自动登录完成: {bastion_name}")
                    except Exception as login_e:
                        main_window_logger.error(f"自动登录过程中发生错误: {login_e}")
                        self.show_error_signal.emit("登录错误", f"自动登录失败: {login_e}")
                    finally:
                        self.remove_status_signal.emit()
                thread = threading.Thread(target=open_bastion_in_thread)
                thread.daemon = True
                thread.start()

    def set_table_style(self,table_view):
        # 设置表格样式
        table_view.setStyleSheet("""
            QTableView {
                background-color: #f0f0f0;
                gridline-color: #d9d9d9;
                border: 1px solid #d9d9d9;
                selection-background-color: #6495ED;
                selection-color: white;
            }
            QTableView::item {
                padding: 5px;
            }
            QTableView::item:selected {
                background-color: #6495ED;
                color: white;
            }
            QTableView::item:hover {
                background-color: #e0e0e0;
            }
            QHeaderView::section {
                background-color: #4CAF50;
                color: white;
                padding: 5px;
                border: 1px solid #d9d9d9;
                font-weight: bold;
            }
            QHeaderView::section:hover {
                background-color: #45a049;
            }
            QHeaderView::section:pressed {
                background-color: #3e8e41;
            }
            /* 新增滚动条样式 */
            QTableView QScrollBar:vertical {
                width: 18px;  /* 设置垂直滚动条宽度 */
            }
            QTableView QScrollBar:horizontal {
            height: 18px;  /* 设置横向滚动条高度 */
            }
        """)



    def load_servers_data(self):
        """从Excel文件加载堡垒机数据"""
        data_loader = bastion_loader.ServersLoader()
        data_loader.load_data()
        data = data_loader.get_sorted_data()
        # 创建模型并设置表头
        model = QStandardItemModel()
        # 使用配置的路段服务器表格列名
        configured_servers_columns = self.servers_config.get_servers_columns()
        model.setHorizontalHeaderLabels(configured_servers_columns)
        # 创建自定义模型并设置表头
        # model = ChineseSortModel()
        # model.setHorizontalHeaderLabels(data.columns.tolist())

        # 填充数据
        for row in data.itertuples():
            items = [QStandardItem(str(col)) for col in row[1:]]
            for item in items:
                item.setFlags(item.flags() | Qt.ItemIsEditable) # 确保单元格可编辑
            model.appendRow(items)

        # 设置模型到表格视图
        self.table_view2.setModel(model)

        # 设置模型到表格视图
        self.table_view2.setModel(model)

        # 设置列宽为可交互调整模式
        header = self.table_view2.horizontalHeader()
        header.setSectionResizeMode(QHeaderView.Interactive)
        # 设置所有列按比例拉伸
        # header.setSectionResizeMode(QHeaderView.Stretch)
        # 设置表格大小策略
        self.table_view2.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        # 启用双击调整为最佳宽度
        self.table_view2.horizontalHeader().setResizeContentsPrecision(100)  # 考虑前100行内容
        # 确保模型支持排序
        model.setSortRole(Qt.DisplayRole)

    def show_config_dialog(self):
        """显示配置对话框"""
        dialog = ConfigDialog(self)
        if dialog.exec_():
            # 获取新的配置
            config = dialog.get_config()
            # 保存配置，但不尝试应用到BastionPageLoader
            # 因为BastionPageLoader目前不支持这些参数
            # 需要提示用户重启应用程序以应用新的设置
            self.show_info_signal.emit(
                "配置已保存",
                "配置已保存，但需要重启应用程序以应用新的设置。"
            )

    def servers_show_config_dialog(self):
        """显示配置对话框"""
        dialog = ServersConfigDialog(self)
        if dialog.exec_():
            # 获取新的配置
            config = dialog.get_config()
            # 保存配置，但不尝试应用到BastionPageLoader
            # 因为BastionPageLoader目前不支持这些参数
            # 需要提示用户重启应用程序以应用新的设置
            self.show_info_signal.emit(
                "配置已保存",
                "配置已保存，但需要重启应用程序以应用新的设置。"
            )

    def reload_all_config(self):
        # 强制重新加载配置，确保获取最新数据
        self.config.load_config()

        # 1. 窗口大小
        width, height = self.config.get_window_size()
        self.resize(width, height)
        # 2. 置顶
        if self.config.get_window_on_top():
            self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
            self.top_button.setText("取消置顶")
        else:
            self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint)
            self.top_button.setText("窗口置顶")
        self.show()
        # 3. 默认提交
        self.auto_submit = self.config.get_auto_submit()
        self.submit_button.setText("提交登录")
        # 4. 日志功能
        from logger_config import logger_config
        # 更新 logger_config 实例的日志启用状态
        logger_config.log_enabled = self.config.get_log_enabled()
        
        if not logger_config.log_enabled:
            logger_config.release_all_log_files()
        else:
            # 启用日志，重新初始化
            logger_config.setup_logger()
        # 5. 重新加载表格数据
        self.load_bastion_data()
        self.load_servers_data()

    def _show_error_box(self, title, msg):
        QMessageBox.critical(self, title, msg)

    def _show_info_box(self, title, msg):
        QMessageBox.information(self, title, msg)

    def _show_status_label(self, msg):
        from PySide2.QtWidgets import QLabel
        if self._status_label:
            self.statusBar().removeWidget(self._status_label)
        self._status_label = QLabel(msg)
        self.statusBar().addWidget(self._status_label)
        self.statusBar().repaint()

    def _remove_status_label(self):
        if self._status_label:
            self.statusBar().removeWidget(self._status_label)
            self._status_label = None
            self.statusBar().repaint()


# 自定义模型类，重写 sort 方法以支持中文排序
class ChineseSortModel(QStandardItemModel):
    def __init__(self, parent=None):
        super().__init__(parent)
    def sort(self, column, order=Qt.AscendingOrder):
        def chinese_sort_key(row):
            item = self.item(row, column)
            if item is None:
                return ""
            text = item.text()
            return ''.join(lazy_pinyin(text))

        # 获取所有行索引
        rows = list(range(self.rowCount()))
        # 按中文排序
        rows.sort(key=chinese_sort_key, reverse=order == Qt.DescendingOrder)

        # 临时存储所有行的数据
        temp_rows = []
        for row in rows:
            temp_row = []
            for col in range(self.columnCount()):
                item = self.takeItem(row, col)
                if item:
                    temp_row.append(item)
                else:
                    temp_row.append(QStandardItem())
            temp_rows.append(temp_row)

        # 清空当前模型
        self.removeRows(0, self.rowCount())

        # 按排序后的顺序插入行
        for temp_row in temp_rows:
            new_row = []
            for item in temp_row:
                new_row.append(item)
            self.appendRow(new_row)

        self.layoutChanged.emit()

    def setup_logger(self):
        if not self.log_enabled:
            return
        # 先移除所有 root logger 的 handler
        root_logger = logging.getLogger()
        for handler in root_logger.handlers[:]:
            handler.close()
            root_logger.removeHandler(handler)
        # 重新配置
        ...